package com.yanti.util;

import com.yanti.domain.enums.RedisKeyEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Component;

import java.util.*;

@Slf4j
@Component
public class RedisCountUtils {

    private final RedisTemplate<String, Object> redisTemplate;

    public RedisCountUtils(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    // ---------------------- 含删除操作的方法 ----------------------

    /**
    * 扫描匹配的键，累加值并删除键（适用于清理场景）
    */
    public long scanSumAndDelete(String pattern) {
        Set<String> keys = scanKeysSafely(pattern);
        long sum = sumValuesByKeys(keys);
        deleteKeys(keys);
        return sum;
    }

    /**
     * 扫描匹配的键，累加值并删除键（适用于清理场景）
     * @param uid 用户ID
     * @param questionIds 问题ID集合
     * @param keyEnum Redis键枚举类型
     * @return 累加后的总时间（单位：毫秒）
     */
    public long sumAndDeleteByQuestionIds(String uid, Set<Long> questionIds, RedisKeyEnum keyEnum) {
        List<String> keysToDelete = new ArrayList<>();
        long totalTime = 0;

        for (Long questionId : questionIds) {
            String key = keyEnum.getKey(uid, questionId.toString());
            Long value = getValueAsLong(key);
            totalTime += value;
            keysToDelete.add(key);
        }
        deleteKeys(keysToDelete);
        return totalTime;
    }

    // ---------------------- 无删除操作的方法 ----------------------

    /**
    * 安全扫描匹配的键集合（仅查询）
    */
    public Set<String> scanKeysSafely(String pattern) {
        ScanOptions options = ScanOptions.scanOptions().match(pattern).count(100).build();
        Set<String> keys = new HashSet<>();
        try (Cursor<String> cursor = redisTemplate.scan(options)) {
            while (cursor.hasNext()) keys.add(cursor.next());
        } catch (Exception e) {
            log.error("SCAN 失败: {}", e.getMessage());
        }
        return keys;
    }

    /**
    * 累加指定键集合的值（仅计算）
    */
    public long sumValuesByKeys(Set<String> keys) {
        long sum = 0;
        for (String key : keys) {
            sum += getValueAsLong(key);
        }
        return sum;
    }

    // ---------------------- 基础工具方法 ----------------------

    /**
     * 批量删除键
     */
    private void deleteKeys(Collection<String> keys) {
        if (!keys.isEmpty()) {
            redisTemplate.delete(keys);
            log.debug("删除键: {}", keys);
        }
    }

    /**
     * 解析 Redis 值为 Long 类型
     * */
    public long getValueAsLong(String key) {
        Object value = redisTemplate.opsForValue().get(key);
        if (value instanceof Number) return ((Number) value).longValue();
        if (value instanceof String) {
            try {
                return Long.parseLong((String) value);
            } catch (NumberFormatException e) {
                log.warn("非数值类型值: Key={}, Value={}", key, value);
            }
        }
        return 0L;
    }
}
